The engine gaps left open after the SDK batch (2026.9.12.2) - #619
Merged
Conversation
Issues #564 to #618 checked against main at c688fca: six were fixed and are closed, two are not engine work, and four remain. Their designs, together with the two gaps the 2026-09-11 record left open, of which one turns out to be misdiagnosed: the per-target tool declaration exists under [target.<selector>.xlings.workspace], measured on linux-x86_64. For review before implementation.
…ask list The four review questions are answered: windows_subsystem takes "windows", windows_entry ships now, a resolve-time refusal is enough for #613, and the graph-wide switch is an abi table. Measuring the plan corrected it three times. The #613 refusal already exists as requires = ["mcpp:c++-abi=libstdc++"]. The whole-graph channel G2 asked for is dialect_cxxflags: -pthread there links the openkal-emscripten threads feature, while the same flag in cxxflags reproduces the recorded error. And a new defect, T1: mcpp build --toolchain llvm@22.1.8 after a gcc build replays the gcc build in 0.00s.
Implements .agents/docs/2026-09-12-engine-gaps-after-the-sdk-batch.md (M1-M9). - #618: `[targets.<name>] windows_subsystem` and `windows_entry`, rendered per ABI onto the declaring executable's own link (`/SUBSYSTEM:` with the CRT `/ENTRY:` symbol on MSVC, `-mwindows`/`-municode` on GNU), inert off PE, and refused on library targets. Build-program protocol 10 adds the `windows-subsystem` and `windows-entry` directives for a named target. - T1: the fast path compares the toolchain request (`--toolchain`, `MCPP_TOOLCHAIN`, and `[toolchain] default`); a build asking for another toolchain no longer replays the previous one. - #615: `runtime.deploy = [{ from, to }]` places runtime files in a directory relative to the executable, in mcpp.toml and in descriptors, and `mcpp pack` carries both `deploy_files` and `deploy` at the same relative paths. - `[target.<selector>.abi] threads` as a typed graph-wide switch, with `requires_abi` on a package or feature refused before compilation when the root does not state it. - #613: a dependency's install hook receives MCPP_COMPILER, MCPP_CXX_STDLIB and the target names, computed by the function the build-program environment uses; docs state the `mcpp:c++-abi` recipe for source-built static packages. - #614: one function decides an xlings invocation's environment, the Windows project scope is restored after each invocation, and xlings' own error lines follow a failed install. - #609 and G1: a documented toolchain hazard, and the refusal that names `[target.<selector>.xlings.workspace]`, with examples/13 using it.
…correct the hook environment Windows CI (clang 20.1.7, x86_64-pc-windows-msvc) crashed compiling directives.cppm. The change introduced constructs of the kind src/pack/pack.cppm records crashing that toolchain: pointers to members of an imported type and a std::span over an exported constexpr array, plus optional-bearing types in an exported interface. They are replaced by plain code: `windows_choice_problem` states the accepted values once for both parsers, the directive check and apply are per field, `invocation_env` returns a plain struct, ScopedInvocationEnv keeps plain members, and the hook scope uses six ScopedEnv locals. tests/e2e/648 measured that a dependency's install hook runs before the toolchain is resolved, because prepare resolves it after the dependency graph. The hook therefore receives the build's target and empty toolchain names; the code comment, docs/22, docs/32, the CHANGELOG and the design record now state this, and 648 asserts it, including that inherited values do not leak through. Test fixes: 645 resolves its helper directory before changing directory and drives `mcpp run` through MCPP_TOOLCHAIN; 647 writes each manifest to its own package directory.
…ersion The first other version found was gcc 13.3.0, which rejects -fmodules, so the leg measured the compiler rather than the fast path. Measured after the change: build A-B-A, run A-B-A, and gcc@16.1.0 -> gcc@15.1.0 with the artefact's version string, all passing.
…rted, not failed macOS and Windows CI found an unchanged second build resolving the toolchain: try_fast_build requires an ELF runtime-validation verdict for every artefact, which Mach-O and PE never record (#400). The control now compares the toolchain= lines the two builds record; identical lines report the host as not measured and print the entry, differing lines fail. The design record notes the ELF-only fast path as outside this change.
This was referenced Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements
.agents/docs/2026-09-12-engine-gaps-after-the-sdk-batch.md, tasks M1 to M9, as one change carrying version 2026.9.12.2. 2026.9.12.1 (#617) was not published, and its CHANGELOG entry is folded into this version. The record's §11 lists the corrections made during implementation.Changes
#618: a Windows GUI executable, declared on its target
[targets.<name>] windows_subsystem = "console" | "windows"andwindows_entry = "main" | "wmain" | "WinMain" | "wWinMain"./SUBSYSTEM:together with/ENTRY:<entry>CRTStartupwhenever either key differs from its default, spelled with-Wl,under a GNU-style driver;-mwindowsand-municode;pe_msvc_abi, extracted frompe_link_flag, so the import library and the subsystem address the same linker.exports.mcpp:windows-subsystem=<target>:<value>andmcpp:windows-entry=<target>:<value>, with a newScope::TargetLink.target_directive_errorchecks them against the manifest beforeapply, on both the run path and the cache-hit path.T1: the fast path compares the toolchain request
mcpp build --toolchain llvm@22.1.8printedFinished dev in 0.00sand left the gcc artefact in place.toolchain=(the--toolchainoverride and[toolchain] default), and both the build and run fast paths compare it.--offline,--lockedand--jobsdo not change what resolution chooses, so they are not compared.try_fast_buildrequires an ELF runtime-validation verdict for every artefact. On macOS and Windows CI, 645's control therefore found an unchanged second build resolving the toolchain. The test compares thetoolchain=lines the two builds record: identical lines report the host as not measured, and differing lines fail. The record's §11 notes the limitation as outside this change.#615:
runtime.deploy[runtime] deploy = [{ from, to }]in mcpp.toml, andruntime.deployin descriptors. Destinations arebin/<to>/<file>, and"."means beside the executable.deployis a key of its own because an older descriptor reader does not terminate on{insidedeploy_files.runtime.deploy. The unit test written for the key reported that gap.mcpp packstages the files of bothdeploy_filesanddeployat the same relative path beside the packed executable, in both the ELF and PE layouts. Before this, pack read neither list.[target.<selector>.abi] threadsandrequires_abi(record §5.2)-pthreadon targets that are neither PE nor freestanding. It is applied to the root'sdialect_cxxflags,cflagsandldflagsand to every dependency'scflags, so it reaches the std module prebuild, the scan, every translation unit, the link and the dependency cache key.requires_abi = { threads = true }on a package or a feature is refused before compilation when the root does not state the switch, naming the package, the feature and the table that satisfies it.[target.<selector>.abi]is reported (abi/dependency-table) and ignored.#613: the install hook's environment
MCPP_TARGETand its three segments, andMCPP_COMPILERandMCPP_CXX_STDLIBpresent and empty, so a hook never reads a value inherited from a parent process.install_hook_envcomputes the six values, andcontract_envnow takes them from it, in the same order, so no build program's re-run key changes.requires = ["mcpp:c++-abi=<stdlib>"]recipe for a source-built static package; the refusal names both implementations once the toolchain is resolved.#614: one decision for an xlings invocation's environment
invocation_envdecides the environment: global mode is an absentXLINGS_PROJECT_DIR.ScopedInvocationEnvapplies the project scope for the lifetime of each runner function and restores the prior value._putenv_s(key, "")already meant removal there; what was wrong was the lifetime.install_packagesfallback no longer spells global mode by hand.platform::env::unsetis explicit.stderr_error_tail.#609 and G1
<xutility>: std::find no longer compiles with structs with defaulted equality comparison with Clang-CL microsoft/STL#6294.[target.<selector>.xlings]refusal names[target.<selector>.xlings.workspace]. examples/13, its README and the iOS simulator CI fixture use that table.Tests
Unit tests:
test_manifest: windows keys,runtime.deploy,requires_abiand the abi table, the G1 refusal, and the generated key list.test_ninja_backend: every row of the subsystem rendering tables, plus a graph test showing the flag reaches only the declaring executable.test_build_directives: scope, refusals and cache round trip of the new directives.test_runtime_contract: the descriptordeployreader.test_xlings:invocation_env, the restore guarantee and the POSIX prefix.test_install_hook_env: a new file.All 112 unit test binaries pass locally.
End-to-end tests:
main.mcpp runleg, and the machine-default leg (newest other installed version, checked in the artefact); reported as not measured on hosts whose fast path declines for another reason.runtime.deployplacement, the test binary layout, the collision and the escape refusal.mcpp packcarries both lists.Ecosystem follow-ups (after release)
requires_abion thethreadsfeature, and the CI engine pin.compat.mysql-connector-cppdeclaresrequires = ["mcpp:c++-abi=libstdc++"], checked against the index floor.